package webSocketTool

import (
	"Gin-Server-01/com/server/core/common"
	"Gin-Server-01/com/server/core/logs"
	"Gin-Server-01/com/server/core/pojo"
	"Gin-Server-01/com/server/core/tools/jsonTool"
	"Gin-Server-01/com/server/service"
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"sync"
	"time"
)

// WsMsg 是 WebSocket 消息的结构体，用于在不同 goroutine 之间共享消息。
type WsMsg struct {
	Up          string      `json:"up"`          // 发送的信息
	Down        string      `json:"down"`        // 接收信息
	IsConnected bool        `json:"IsConnected"` // 连接状态
	MutexLock   sync.Mutex  //互斥锁
	Objs        interface{} `json:"objs"` //数据
}

// 协议升级
var (
	upgrader = websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}
)

// 全局变量等待组
var wg sync.WaitGroup

// readMessages 从 WebSocket 连接中读取消息。
// 该函数在连接关闭时结束，使用传入的 WebSocket 连接和共享的 WsMsg 结构体。
// 结束时释放相关资源。
func readMessages(ctx context.Context, conn *websocket.Conn, wsMsg *WsMsg) {
	defer conn.Close()

	for {
		select {
		case <-ctx.Done():
			log.Println("readMessages goroutine stopped\n")
			return
		default:
			_, p, err := conn.ReadMessage()
			if err != nil {
				//如果有人退出就执行
				log.Println(err.Error() + "\n")
				return
			}

			toString := string(p)
			wsObjs := pojo.WsObjs{}
			wsMsg.MutexLock.Lock()
			wsMsg.Down = toString
			log.Println("【WS】源信息:" + toString)
			jsonTool.JSONToStruct(wsMsg.Down, &wsObjs)

			//todo:业务逻辑
			//wsObjs.Actions
			//聊天逻辑
			log.Println("【ws:method】>>>>>>>>>>>>>>>>>>>" + wsObjs.Actions.Url + "<<<<<<<<<<<<<<")

			switch wsObjs.Actions.Url {
			case "chat_post":
				service.ChatPostService(ctx, conn, &wsObjs)
			case "chat_delete":
				service.ChatDeleteService(ctx, conn, &wsObjs)
			case "chat_get":
				service.ChatGetService(ctx, conn, &wsObjs)
			case "chat_update":
			default:
				response := common.Response{
					StatusCode: http.StatusNotFound,
					Message:    "无响应",
					Data:       nil,
				}
				conn.WriteMessage(websocket.TextMessage, []byte(jsonTool.JsonFormatString(response)))
				return
			}

			//todo:发送信息  conn.WriteMessage(websocket.TextMessage, []byte(jsonTool.JsonFormatString(wsMsg)))

			log.Println("【WS】", fmt.Sprintf("WebSocket:接收信息:%s\n", jsonTool.JsonFormatString(wsObjs)))

			wsMsg.MutexLock.Unlock()

		}
	}
}

// writeMessages 定期从共享的 WsMsg 结构体中获取消息并发送到 WebSocket 连接。
// 该函数在连接关闭时结束，使用传入的 WebSocket 连接和共享的 WsMsg 结构体。
// 结束时释放相关资源。
func writeMessages(ctx context.Context, conn *websocket.Conn, wsMsg *WsMsg) {
	defer conn.Close()

	ticker := time.NewTicker(200 * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			logs.DaoPrintln("写入消息goroutine已停止")
			return
		case <-ticker.C:
			wsMsg.MutexLock.Lock()
			if len(wsMsg.Up) != 0 {
				p := []byte(wsMsg.Up)
				err := conn.WriteMessage(websocket.TextMessage, p)
				if err != nil {
					log.Println(err)
					return
				}
				wsMsg.Up = ""
			} else {
				time.Sleep(200 * time.Millisecond)
				//log.Println("睡觉...")
			}

			wsMsg.MutexLock.Unlock()
		}
	}
}

// WsHandlerPlus 创建 WebSocket 连接处理函数。
// 该函数升级 HTTP 连接为 WebSocket 连接，启动读取和写入 goroutine，并等待它们结束。
// 使用传入的共享 WsMsg 结构体来传递消息。
func WsHandlerPlus(wsMsg *WsMsg) gin.HandlerFunc {
	log.Println("======初始化WS:=======")
	return func(c *gin.Context) {
		conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
		if err != nil {
			log.Println(err)
			return
		}

		// 设置连接状态为已连接
		wsMsg.MutexLock.Lock()
		wsMsg.IsConnected = true
		wsMsg.MutexLock.Unlock()

		ctx, cancel := context.WithCancel(context.Background())
		defer func() {
			// 设置连接状态为已断开
			wsMsg.MutexLock.Lock()
			wsMsg.IsConnected = false
			wsMsg.MutexLock.Unlock()
			cancel()
		}()

		wg.Add(2)

		// 启动独立的 goroutine 进行读取和写入
		go func() {
			readMessages(ctx, conn, wsMsg)
		}()

		go func() {
			writeMessages(ctx, conn, wsMsg)
		}()

		// 等待两个 goroutine 结束
		wg.Wait()
	}
}
